home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / gs3.53 / gs_fonts.ps < prev    next >
Text File  |  1996-01-10  |  23KB  |  733 lines

  1. %    Copyright (C) 1990, 1995 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % Font initialization and management code.
  16.  
  17. % Define the default font.
  18. /defaultfontname /Courier def
  19.  
  20. % Define the name of the font map file.
  21. /FONTMAP dup where { pop pop } { (Fontmap) def } ifelse
  22.  
  23. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  24. % (This is intended primarily for machines with very small memories.)
  25. % In this case, we define another dictionary, parallel to FontDirectory,
  26. % that retains an open file for every font loaded.
  27. /FontFileDirectory 10 dict def
  28.  
  29. % Load the font name -> font file name map.
  30. userdict /Fontmap FontDirectory maxlength dict put
  31. /.loadFontmap        % <file> .loadFontmap -
  32.  {  { dup token not { closefile exit } if
  33.         % stack: <file> fontname
  34.       1 index token not
  35.        { (Fontmap entry for ) print dup =only
  36.      ( has no associated file or alias name!  Giving up.\n) print flush
  37.      {.loadFontmap} 0 get 1 .quit
  38.        } if
  39.       dup type dup /stringtype eq exch /nametype eq or not
  40.        { (Fontmap entry for ) print 1 index =only
  41.      ( has an invalid file or alias name!  Giving up.\n) print flush
  42.      {.loadFontmap} 0 get 1 .quit
  43.        } if
  44.         % stack: <file> fontname filename|aliasname
  45.         % Read and pop tokens until a semicolon.
  46.        { 2 index token not
  47.       { (Fontmap entry for ) print 1 index =only
  48.         ( ends prematurely!  Giving up.\n) print flush
  49.         {.loadFontmap} 0 get 1 .quit
  50.       } if
  51.      dup /; eq { pop .definefontmap exit } if
  52.      pop
  53.        } loop
  54.     } loop 
  55.  } bind def
  56. % Make an entry in Fontmap.  We redefine this if the Level 2
  57. % resource machinery is loaded.
  58. /.definefontmap            % <fontname> <file|alias> .definefontmap -
  59.  { Fontmap 3 1 roll .growput
  60.  } bind def
  61.  
  62. % Parse a font file just enough to find the FontName or FontType.
  63. /.findfontvalue        % <file> <key> .findfontvalue <value> true
  64.             % <file> <key> .findfontvalue false
  65.             % Closes the file in either case.
  66.  { exch dup read not { -1 } if
  67.    2 copy unread 16#80 eq
  68.     { dup (xxxxxx) readstring pop pop }        % skip .PFB header
  69.    if
  70.         % Stack: key file
  71.     { dup token not { false exit } if        % end of file
  72.       dup /eexec eq { pop false exit } if    % reached eexec section
  73.       dup /Subrs eq { pop false exit } if    % Subrs without eexec
  74.       dup /CharStrings eq { pop false exit } if    % CharStrings without eexec
  75.       dup 3 index eq
  76.        { xcheck not { dup token exit } if }    % found key
  77.        { pop }
  78.       ifelse
  79.     } loop
  80.         % Stack: key file value true   (or)
  81.         % Stack: key file false
  82.    dup { 4 } { 3 } ifelse -2 roll closefile pop
  83.  } bind def
  84. /.findfontname
  85.  { /FontName .findfontvalue
  86.  } bind def
  87.  
  88. % If there is no FONTPATH, try to get one from the environment.
  89. NOFONTPATH { systemdict /FONTPATH undef (%END FONTPATH) .skipeof } if
  90. /FONTPATH where
  91.  { pop
  92.  }
  93.  { (GS_FONTPATH) getenv
  94.     { /FONTPATH exch def }
  95.     { (%END FONTPATH) .skipeof }
  96.    ifelse
  97.  }
  98. ifelse
  99.  
  100. % Scan directories looking for plausible fonts.  "Plausible" means that
  101. % the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001
  102. % followed by four arbitrary bytes and then either of these strings.
  103. % To speed up the search, we skip any file whose name appears in
  104. % the Fontmap (with any extension and upper/lower case variation) already,
  105. % and any file whose extension definitely indicates it is not a font.
  106. %
  107. % NOTE: The current implementation of this procedure is Unix/DOS-
  108. % specific.  It assumes that '/' and '\' are directory separators; that
  109. % the part of a file name following the last '.' is the extension;
  110. % that ';' cannot appear in a file name; and that ':' can appear in a
  111. % file name only if the file name doesn't begin with '/', '\', or '.'.
  112. % (this is so that Unix systems can use ':' as the separator).
  113. %
  114. /.lowerstring        % <string> .lowerstring <lowerstring>
  115.  { 0 1 2 index length 1 sub
  116.     { 2 copy get dup 65 ge exch 90 le and
  117.        { 2 copy 2 copy get 32 add put }
  118.      if pop
  119.     }
  120.    for
  121.  } bind def
  122. /.splitfilename        % <dir.../base.extn> .basename <base> <extn>
  123.  {  { (/) search { true } { (\\) search } ifelse
  124.        { pop pop }
  125.        { exit }
  126.       ifelse
  127.     }
  128.    loop
  129.    dup { (.) search { pop pop } { exit } ifelse } loop
  130.    2 copy eq
  131.     { pop () }
  132.     { exch dup length 2 index length 1 add sub 0 exch getinterval exch }
  133.    ifelse
  134. % Following is debugging code.
  135. %   (*** Split => ) print 2 copy exch ==only ( ) print ==only
  136. %   ( ***\n) print flush
  137.  } bind def
  138. /.scanfontdict Fontmap maxlength dict def
  139. /.scanfontbegin
  140.  {    % Construct the table of all file names already in Fontmap.
  141.    Fontmap
  142.     { exch pop dup type /stringtype eq
  143.        { .splitfilename pop =string copy .lowerstring cvn
  144.      .scanfontdict exch true .growput
  145.        }
  146.        { pop
  147.        }
  148.       ifelse
  149.     }
  150.    forall
  151.  } bind def
  152. /.scanfontskip mark
  153.         % Strings are converted to names anyway, so....
  154.   /afm true
  155.   /bat true
  156.   /c true
  157.   /cmd true
  158.   /com true
  159.   /dll true
  160.   /doc true
  161.   /exe true
  162.   /h true
  163.   /o true
  164.   /obj true
  165.   /pfm true
  166.   /txt true
  167. .dicttomark def
  168. /.scan1fontstring 128 string def
  169. /.fontheaders [(%!PS-AdobeFont*) (%!FontType1*)] def
  170. 0 .fontheaders { length max } forall 6 add    % extra for PFB header
  171. /.scan1fontfirst exch string def
  172. /.scan1fontdir        % <dirname> .scan1fontdir -
  173.  { QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
  174.    (/*) concatstrings 0 0 0 4 -1 roll    % found scanned files
  175.     {        % stack: <fontcount> <scancount> <filecount> <filename>
  176.       exch 1 add exch                   % increment filecount
  177.       dup .splitfilename .lowerstring
  178.         % stack: <fontcount> <scancount> <filecount+1> <filename>
  179.         %    <BASE> <ext>
  180.       .scanfontskip exch known exch .scanfontdict exch known or
  181.        { pop
  182.         % stack: <fontcount> <scancount> <filecount+1>
  183.        }
  184.        { 3 -1 roll 1 add 3 1 roll
  185.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  186.      dup (r) { file } stopped
  187.       { pop pop null () 
  188.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  189.         %    null ()
  190.       }
  191.       { 
  192.         % On some platforms, the file operator will open directories,
  193.         % but an error will occur if we try to read from one.
  194.         % Handle this possibility here.
  195.         dup .scan1fontfirst { readstring } stopped
  196.          { pop pop () }
  197.          { pop }
  198.         ifelse 
  199.         % stack: <fontcount> <scancount+1> <filecount+1>
  200.         %    <filename> <file> <header>
  201.       }
  202.      ifelse
  203.         % Check for PFB file header.
  204.      dup (\200\001????*) .stringmatch
  205.       { dup length 6 sub 6 exch getinterval }
  206.      if
  207.         % Check for font file headers.
  208.      false .fontheaders { 2 index exch .stringmatch or } forall exch pop
  209.       {    % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  210.         %    <file>
  211.         dup 0 setfileposition .findfontname
  212.          { dup Fontmap exch known
  213.         { pop pop
  214.         }
  215.         { exch copystring exch
  216.           DEBUG { ( ) print dup =only } if
  217.           1 index .definefontmap
  218.           .splitfilename pop true .scanfontdict 3 1 roll .growput
  219.             % Increment fontcount.
  220.           3 -1 roll 1 add 3 1 roll
  221.         }
  222.            ifelse
  223.          }
  224.         if
  225.       }
  226.         % .findfontname will have done a closefile in the above case.
  227.       { dup null eq { pop } { closefile } ifelse pop 
  228.       }
  229.      ifelse
  230.        }
  231.       ifelse
  232.     }
  233.    .scan1fontstring filenameforall
  234.    QUIET
  235.     { pop pop pop }
  236.     { ( ) print =only ( files, ) print =only ( scanned, ) print
  237.       =only ( new fonts.\n) print flush
  238.     }
  239.    ifelse
  240.  } bind def
  241. % Scan all the directories mentioned in FONTPATH (or GS_FONTPATH).
  242. /.scanfontpath
  243.  { .scanfontbegin
  244.     % Parsing the list of dictionaries is messy, since we have to
  245.     % handle both the Unix : and the other-system ; as separators.
  246.     % See the earlier comment for the restrictions that make this work.
  247.    FONTPATH
  248.     { dup length 0 eq { pop exit } if
  249.       (;) search
  250.        { exch pop
  251.        }
  252.        { dup 0 1 getinterval (/\\.) exch search
  253.       { pop pop pop (:) search
  254.          { exch pop }
  255.          { () exch }
  256.         ifelse
  257.       }
  258.       { pop () exch
  259.       }
  260.      ifelse
  261.        }
  262.       ifelse .scan1fontdir
  263.     }
  264.    loop
  265.  } bind def
  266.  
  267. %END FONTPATH
  268.  
  269. % Define definefont.  This is a procedure built on a set of operators
  270. % that do all the error checking and key insertion.
  271. mark
  272.     /.buildfont0 where { pop 0 /.buildfont0 cvx } if
  273.     /.buildfont1 where { pop 1 /.buildfont1 cvx } if
  274.     /.buildfont3 where { pop 3 /.buildfont3 cvx } if
  275.     /.buildfont4 where { pop 4 /.buildfont4 cvx } if
  276. .dicttomark /buildfontdict exch def
  277. /.growfontdict
  278.  {    % Grow the font dictionary, if necessary, to ensure room for an
  279.     % added entry, making sure there is at least one slot left for FID.
  280.    dup maxlength 1 index length sub 2 lt
  281.     { dup dup wcheck
  282.        { .growdict }
  283.        { .growdictlength dict copy }
  284.       ifelse
  285.     }
  286.     { dup wcheck not { dup maxlength dict copy } if
  287.     }
  288.    ifelse
  289.  } bind def  
  290. /definefont
  291.  { 1 dict begin count /d exch def    % save stack depth in case of error
  292.     {        % Check for disabled platform fonts.
  293.       NOPLATFONTS
  294.        {    % Make sure we leave room for FID.
  295.      .growfontdict dup /ExactSize 0 put
  296.        }
  297.        {    % Hack: if the Encoding looks like it might be the
  298.         % Symbol or Dingbats encoding, load those now (for the
  299.         % benefit of platform font matching) just in case
  300.         % the font didn't actually reference them.
  301.      dup /Encoding get length 65 ge
  302.       { dup /Encoding get 64 get
  303.         dup /congruent eq { SymbolEncoding pop } if
  304.         /a9 eq { DingbatsEncoding pop } if
  305.       }
  306.      if
  307.        }
  308.       ifelse
  309.       dup /FontType get //buildfontdict exch get exec
  310.       DISKFONTS
  311.        { FontFileDirectory 2 index known
  312.       { dup /FontFile FontFileDirectory 4 index get .growput
  313.       }
  314.      if
  315.        }
  316.       if
  317.       readonly
  318.     }
  319.    stopped
  320.     { count d sub { pop } repeat end /invalidfont signalerror
  321.     }
  322.     { end        % stack: name fontdict
  323.         % If the current allocation mode is global, also enter
  324.         % the font in LocalFontDirectory.
  325.       .currentglobal
  326.        { systemdict /LocalFontDirectory .knownget
  327.       { 2 index 2 index .growput }
  328.      if
  329.        }
  330.       if
  331.       dup FontDirectory 4 -2 roll .growput
  332.     }
  333.    ifelse
  334.  } odef
  335.  
  336. % Define a procedure for defining aliased fonts.
  337. % We can't just copy the font (or even use the same font unchanged),
  338. % because a significant number of PostScript files assume that
  339. % the FontName of a font is the same as the font resource name or
  340. % the key in [Shared]FontDirectory; on the other hand, some Adobe files
  341. % rely on the FontName of a substituted font *not* being the same as
  342. % the requested resource name.  We address this issue heuristically:
  343. % we substitute the new name iff the font name doesn't have MM in it.
  344. /.aliasfont        % <name> <font> .aliasfont <newFont>
  345.  { .currentglobal 3 1 roll dup .gcheck .setglobal
  346.    dup length 2 add dict
  347.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  348.         % Stack: global fontname newfont newfont.
  349.         % We might be defining a global font whose FontName
  350.         % is a local string.  This is weird, but legal,
  351.         % and doesn't cause problems anywhere else.
  352.         % To avoid any possible problems, do a cvn.
  353.    2 index =string cvs (MM) search
  354.     { pop pop pop pop
  355.     }
  356.     { /FontName exch dup type /stringtype eq { cvn } if put
  357.     }
  358.    ifelse
  359.    systemdict /definefont get exec    % Don't bind, since Level 2
  360.                     % redefines definefont
  361.    exch .setglobal
  362.  } odef        % so findfont will bind it
  363.  
  364. % Define .loadfontfile for loading a font.  If we recognize Type 1 fonts,
  365. % gs_type1.ps will redefine this.
  366. /.loadfontfile { cvx exec } bind def
  367. /.loadfont
  368.  {        % Some buggy fonts leave extra junk on the stack,
  369.         % so we have to make a closure that records the stack depth
  370.         % in a fail-safe way.
  371.    /.loadfontfile cvx count 1 sub 2 packedarray cvx exec
  372.    count exch sub { pop } repeat
  373.  } bind def
  374.  
  375. % Find an alternate font to substitute for an unknown one.
  376. % We go to some trouble to parse the font name and extract
  377. % properties from it.  Later entries take priority over earlier.
  378. /.substitutefaces [
  379.     % Guess at suitable substitutions for random unknown fonts.
  380.   [(Grot) /Times]
  381.   [(Roman) /Times]
  382.   [(Book) /NewCenturySchlbk]
  383.     % If the family name appears in the font name,
  384.     % use a font from that family.
  385.   [(Arial) /Helvetica]
  386.   [(Avant) /AvantGarde]
  387.   [(Bookman) /Bookman]
  388.   [(Century) /NewCenturySchlbk]
  389.   [(Cour) /Courier]
  390.   [(Geneva) /Helvetica]
  391.   [(Helv) /Helvetica]
  392.   [(NewYork) /Times]
  393.   [(Pala) /Palatino]
  394.   [(Sans) /Helvetica]
  395.   [(Schlbk) /NewCenturySchlbk]
  396.   [(Serif) /Times]
  397.   [(Swiss) /Helvetica]
  398.   [(Times) /Times]
  399.     % Substitute for Adobe Multiple Master fonts.
  400.   [(Myriad) /Times]
  401.   [(Minion) /Helvetica]
  402.     % Condensed or narrow fonts map to the only narrow family we have.
  403.   [(Cond) /Helvetica-Narrow]
  404.   [(Narrow) /Helvetica-Narrow]
  405.     % If the font wants to be monospace, use Courier.
  406.   [(Monospace) /Courier]
  407.   [(Typewriter) /Courier]
  408. ] readonly def
  409. /.substituteproperties [
  410.   [(It) 1] [(Oblique) 1]
  411.   [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2]
  412. ] readonly def
  413. /.substitutefamilies mark
  414.   /AvantGarde
  415.     {/AvantGarde-Book /AvantGarde-BookOblique
  416.      /AvantGarde-Demi /AvantGarde-DemiOblique}
  417.   /Bookman
  418.     {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic}
  419.   /Courier
  420.     {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique}
  421.   /Helvetica
  422.     {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
  423.   /Helvetica-Narrow
  424.     {/Helvetica-Narrow /Helvetica-Narrow-Oblique
  425.      /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique}
  426.   /NewCenturySchlbk
  427.     {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic
  428.      /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic}
  429.   /Palatino
  430.     {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic}
  431.   /Times
  432.     {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic}
  433. .dicttomark readonly def
  434. /.substitutefont        % <fontname> .substitutefont <altname>
  435.  {    % Look for properties and/or a face name in the font name.
  436.     % If we find any, use Helvetica as the base font;
  437.     % otherwise, use the default font.
  438.     % Note that the "substituted" font name may be the same as
  439.     % the requested one; the caller must check this.
  440.    dup length string cvs
  441.     {defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
  442.    exch 0 exch    % stack: fontname facelist properties fontname
  443.     % Look for a face name.
  444.    .substitutefaces
  445.     { 2 copy 0 get search
  446.        { pop pop pop 1 get .substitutefamilies exch get
  447.      4 -1 roll pop 3 1 roll
  448.        }
  449.        { pop pop
  450.        }
  451.       ifelse
  452.     }
  453.    forall
  454.    .substituteproperties
  455.     { 2 copy 0 get search
  456.        { pop pop pop 1 get 3 -1 roll or exch }
  457.        { pop pop }
  458.       ifelse
  459.     }
  460.    forall pop get
  461.     % If SUBSTFONT is defined, use it.
  462.    /SUBSTFONT where
  463.     { pop pop /SUBSTFONT load cvn }
  464.     { exec }
  465.    ifelse
  466.     % Only accept fonts known in the Fontmap.
  467.    Fontmap 1 index known not { pop defaultfontname } if
  468.  } bind def
  469.  
  470. % If requested, make (and recognize) fake entries in FontDirectory for fonts
  471. % present in Fontmap but not actually loaded.  Thanks to Ray Johnston for
  472. % the idea behind this code.
  473. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if
  474.  
  475. % We use the presence or absence of the FontMatrix key to indicate whether
  476. % a font is real or fake.
  477.  
  478. /definefont        % <name> <font> definefont <font>
  479.  { dup /FontMatrix known not { /FontName get findfont } if
  480.    //definefont
  481.  } bind odef
  482.  
  483. /scalefont        % <font> <scale> scalefont <font>
  484.  { exch dup /FontMatrix known not { /FontName get findfont } if
  485.    exch //scalefont
  486.  } bind odef
  487.  
  488. /makefont        % <font> <matrix> makefont <font>
  489.  { exch dup /FontMatrix known not { /FontName get findfont } if
  490.    exch //makefont
  491.  } bind def
  492.  
  493. /setfont        % <font> setfont -
  494.  { dup /FontMatrix known not { /FontName get findfont } if
  495.    //setfont
  496.  } bind odef
  497.  
  498. %END FAKEFONTS
  499.  
  500. % Define findfont so it tries to load a font if it's not found.
  501. % The Red Book requires that findfont be a procedure, not an operator.
  502. /findfont
  503.  {    % Since PostScript has no concept of goto, or even blocks with
  504.     % exits, we use a loop as a way to get an exitable scope.
  505.     % The loop is never executed more than once.
  506.    mark exch
  507.     { .findfontloop
  508.     } stopped
  509.     { counttomark 1 sub { pop } repeat exch pop stop
  510.     }
  511.     {    % Define any needed aliases.
  512.       counttomark 1 sub { .aliasfont } repeat
  513.       exch pop
  514.     }
  515.    ifelse
  516.  } bind def
  517. /.checkalias        % -mark- <alias1> ... <name> .checkalias <<same>>
  518.  { counttomark 1 sub -1 1
  519.     { index 1 index eq
  520.        {        % We're about to try finding a font that's already
  521.             % in our list of aliases, so we're in a loop.
  522.      pop QUIET not
  523.       { (Unable to substitute for font.\n) print flush
  524.       } if
  525.      /findfont cvx /invalidfont signalerror
  526.        }
  527.       if
  528.     }
  529.    for
  530.  } bind def
  531. /.fontknownget        % <fontdir> <fontname> .fontknown <font> true
  532.             % <fontdir> <fontname> .fontknown false
  533.  { .knownget
  534.     { FAKEFONTS
  535.        { dup /FontMatrix known { true } { pop false } ifelse }
  536.        { true }
  537.       ifelse
  538.     }
  539.     { false
  540.     }
  541.    ifelse
  542.  } bind def
  543. /.findfontloop
  544.  {            % We eventually exit this loop with either
  545.             % <font> true or false on the top of the stack.
  546.     {
  547.         % Stack: mark <alias>* fontname
  548.  
  549.             % Already loaded?
  550.     FontDirectory 1 index .fontknownget
  551.      { exch pop true exit }
  552.     if
  553.  
  554.             % Unknown font name?
  555.     dup Fontmap exch .knownget not
  556.      { false exit }
  557.     if
  558.  
  559.             % Font alias?
  560.     dup type /nametype eq
  561.      { .checkalias .findfontloop true exit }
  562.     if
  563.  
  564.             % Font with a procedural definition?
  565.     dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and
  566.      { exec        % The procedure will load the font.
  567.             % Check to make sure this really happened.
  568.        FontDirectory 1 index .knownget
  569.         { exch pop true }
  570.         { false }
  571.        ifelse exit
  572.      }
  573.     if
  574.  
  575.             % Can we open the file?
  576.     findlibfile not
  577.      { QUIET not
  578.         { (Can't find \(or can't open\) font file ) print dup print
  579.           (.\n) print flush
  580.         }
  581.        if pop false exit
  582.      }
  583.     if
  584.  
  585.             % Stack: fontname fontfilename fontfile
  586.     DISKFONTS
  587.      { .currentglobal true .setglobal
  588.        2 index (r) file
  589.        FontFileDirectory exch 4 index exch .growput
  590.        .setglobal
  591.      }
  592.     if
  593.     QUIET not
  594.      { (Loading ) print 2 index =only
  595.        ( font from ) print 1 index print (... ) print flush
  596.      }
  597.     if
  598.     % If LOCALFONTS isn't set, load the font into local or global
  599.     % VM according to FontType; if LOCALFONTS is set, load the font
  600.     % into the current VM, which is what Adobe printers (but not
  601.     % DPS or CPSI) do.
  602.     LOCALFONTS { false } { /setglobal where } ifelse
  603.      { pop /FontType .findfontvalue { 1 eq } { false } ifelse
  604.         % .setglobal, like setglobal, aliases FontDirectory to
  605.         % GlobalFontDirectory if appropriate.  However, we mustn't
  606.         % allow the current version of .setglobal to be bound in,
  607.         % because it's different depending on language level.
  608.        .currentglobal exch /.setglobal load exec
  609.         % Remove the fake definition, if any.
  610.        FontDirectory 3 index undef
  611.        1 index (r) file .loadfont FontDirectory exch
  612.        /.setglobal load exec
  613.      }
  614.      { .loadfont FontDirectory
  615.      }
  616.     ifelse
  617.         % Stack: fontname fontfilename fontdirectory
  618.     QUIET not
  619.      { systemdict /level2dict known
  620.         { .currentglobal false .setglobal vmstatus
  621.           true .setglobal vmstatus 3 -1 roll pop
  622.           6 -1 roll .setglobal 5
  623.         }
  624.         { vmstatus 3
  625.         }
  626.        ifelse { =only ( ) print } repeat
  627.        (done.\n) print flush
  628.      } if
  629.  
  630.         % Check to make sure the font was actually loaded.
  631.     dup 3 index .fontknownget
  632.      { 4 1 roll pop pop pop true exit } if
  633.  
  634.         % Maybe the file had a different FontName.
  635.         % See if we can get a FontName from the file, and if so,
  636.         % whether a font by that name exists now.
  637.     exch (r) file .findfontname
  638.      { 2 copy .fontknownget
  639.         {    % Yes.  Stack: origfontname fontdirectory filefontname fontdict
  640.           3 -1 roll pop exch
  641.           QUIET
  642.            { pop
  643.            }
  644.            { (Using ) print =only
  645.              ( font for ) print 1 index =only
  646.              (.\n) print flush
  647.            }
  648.           ifelse true exit
  649.         }
  650.        if pop
  651.      }
  652.     if pop
  653.  
  654.         % The font definitely did not load correctly.
  655.     QUIET not
  656.      { (Loading ) print dup =only
  657.        ( font failed.\n) print flush
  658.      } if
  659.     false exit
  660.  
  661.     } loop        % end of loop
  662.  
  663.             % Check whether we actually got a font.
  664.    not
  665.     { dup defaultfontname eq
  666.        { QUIET not
  667.       { (Unable to load default font ) print
  668.          dup =only (!  Giving up.\n) print flush
  669.       }
  670.      if /findfont cvx /invalidfont signalerror
  671.        }
  672.       if dup .substitutefont
  673.       2 copy eq { pop defaultfontname } if
  674.       .checkalias
  675.       QUIET not
  676.        { (Substituting font ) print dup =only ( for ) print
  677.      1 index =only (.\n) print flush
  678.        }
  679.       if .findfontloop
  680.     }
  681.    if
  682.  
  683.  } bind def
  684.  
  685. % Define a procedure to load all known fonts.
  686. % This isn't likely to be very useful.
  687. /loadallfonts
  688.  { Fontmap { pop findfont pop } forall
  689.  } bind def
  690.  
  691. % Install initial fonts from FONTPATH or Fontmap.
  692. /.loadinitialfonts
  693.  { /FONTPATH where
  694.     { pop DEBUG { (gs_fonts .scanfontpath) = } if
  695.       .scanfontpath
  696.     }
  697.     { NOFONTMAP not
  698.        { FONTMAP VMDEBUG
  699.      FONTMAP findlibfile
  700.       { exch pop .loadFontmap }
  701.       { FONTMAP /undefinedfilename signalerror }
  702.      ifelse
  703.        }
  704.       if
  705.     }
  706.    ifelse
  707.  
  708.    FAKEFONTS
  709.     { (gs_fonts FAKEFONTS) VMDEBUG
  710.     % Now load all the fonts defined in the Fontmap into FontDirectory
  711.     % as "fake" fonts i.e., font dicts with only FontName defined.
  712.     % We must ensure that this happens in both global and local
  713.     % directories.
  714.       2
  715.     { .currentglobal not .setglobal
  716.       Fontmap
  717.        { pop dup type /stringtype eq { cvn } if
  718.          FontDirectory 1 index known not
  719.           { 1 dict dup /FontName 3 index put        
  720.             FontDirectory 3 1 roll put
  721.           }
  722.          if
  723.        }
  724.       forall
  725.        }
  726.       repeat
  727.     } if
  728.  
  729.  } def            % don't bind, .current/setglobal get redefined
  730.